package app

import (
	"fmt"
	"net/http"
	gourl "net/url"
	"os"
	"os/signal"
	"runtime"
	"sunAb/config"
	"sunAb/flag"
	"time"

	"github.com/rakyll/hey/requester"
)

var (
	proxyURL           *gourl.URL
	h2                 = false
	testing_count      = 50
	testing_time       = time.Duration(0)
	disableRedirects   = false
	disableKeepAlives  = false
	disableCompression = false
	output             = ""
)

func Run(fConfig flag.FlagData) error {
	config, err := config.Decode(fConfig)

	if err != nil {
		return err
	}

	fmt.Println(config)

	if err := request(config, fConfig); err != nil {
		return err
	}

	return nil
}

func request(config config.Conf, fConfig flag.FlagData) error {
	header := make(http.Header)
	// 获取配置文件中设置的headers
	for headerIndex := 0; headerIndex < len(config.Globalheaders); headerIndex++ {
		_header := config.Globalheaders[headerIndex]

		header.Set(_header.Key, _header.Value)
	}

	runtime.GOMAXPROCS(-1)

	// 开始批量压测
	for sceneIndex := 0; sceneIndex < len(config.Scene); sceneIndex++ {
		scene := config.Scene[sceneIndex]

		fmt.Println("开始压测场景：", scene.Name)

		for urlIndex := 0; urlIndex < len(scene.Urls); urlIndex++ {
			_url := scene.Urls[urlIndex]

			fmt.Println("压测地址：", _url.Name)

			url := _url.Url

			method := _url.Method

			req, err := http.NewRequest(method, url, nil)

			if err != nil {
				usageAndExit(err.Error())
			}

			var bodyAll []byte

			if _url.Data != "" {
				bodyAll = []byte(_url.Data)
			}

			dur := testing_time

			// 设置场景里URL设置的headers
			for _urlHeadersIndex := 0; _urlHeadersIndex < len(_url.Headers); _urlHeadersIndex++ {
				_header := _url.Headers[_urlHeadersIndex]
				header.Set(_header.Key, _header.Value)
			}

			req.Header = header

			w := &requester.Work{
				Request:            req,
				RequestBody:        bodyAll,
				N:                  int(fConfig.Number),
				C:                  testing_count,
				QPS:                fConfig.Qps,
				Timeout:            int(fConfig.TimeOut),
				DisableCompression: disableCompression,
				DisableKeepAlives:  disableKeepAlives,
				DisableRedirects:   disableRedirects,
				H2:                 h2,
				ProxyAddr:          proxyURL,
				Output:             output,
			}

			w.Init()

			c := make(chan os.Signal, 1)

			signal.Notify(c, os.Interrupt)

			go func() {
				<-c
				w.Stop()
			}()

			if dur > 0 {
				go func() {
					time.Sleep(dur)
					w.Stop()
				}()
			}

			w.Run()
		}
	}

	return nil
}

func usageAndExit(msg string) {
	if msg != "" {
		fmt.Fprintf(os.Stderr, msg)
		fmt.Fprintf(os.Stderr, "\n\n")
	}
	fmt.Fprintf(os.Stderr, "\n")
	os.Exit(1)
}
